package com.hxgis.common.service.graph;

import wContour.Contour;
import wContour.Global.Border;
import wContour.Global.PolyLine;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;

/**
 * 专题图绘制类
 *
 * @author BLQ
 */
public class MeteoGraph {

    /*
     * 文字对齐方式
     */
    public enum TextAlign {
        TEXT_LEFT, TEXT_CENTER, TEXT_RIGHT
    }

    private BufferedImage graph;
    private int width;
    private int height;
    private float minLon, minLat, maxLon, maxLat;
    private Graphics2D g;
    private float xDelt;
    private float yDelt;

    public float getxDelt() {
        return xDelt;
    }

    public void setxDelt(float xDelt) {
        this.xDelt = xDelt;
    }

    public float getyDelt() {
        return yDelt;
    }

    public void setyDelt(float yDelt) {
        this.yDelt = yDelt;
    }

    public float getMinLon() {
        return minLon;
    }

    public void setMinLon(float minLon) {
        this.minLon = minLon;
    }

    public float getMinLat() {
        return minLat;
    }

    public void setMinLat(float minLat) {
        this.minLat = minLat;
    }

    public float getMaxLon() {
        return maxLon;
    }

    public void setMaxLon(float maxLon) {
        this.maxLon = maxLon;
    }

    public float getMaxLat() {
        return maxLat;
    }

    public void setMaxLat(float maxLat) {
        this.maxLat = maxLat;
    }

    public int getWidth() {
        return width;
    }

    public void setWidth(int width) {
        this.width = width;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public BufferedImage getGraph() {
        return graph;
    }

    public void setGraph(BufferedImage graph) {
        this.graph = graph;
    }

    /**
     * 构造函数
     *
     * @param width  图片宽
     * @param height 图片高
     * @param minLon 图片左上角经度
     * @param maxLon 图片右下角经度
     * @param minLat 图片右下角纬度
     * @param maxLat 图片左上角纬度
     */
    public MeteoGraph(int width, int height, float minLon, float maxLon,
                      float minLat, float maxLat) {
        this.graph = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_ARGB);
        this.width = width;
        this.height = height;
        this.minLon = minLon;
        this.minLat = minLat;
        this.maxLon = maxLon;
        this.maxLat = maxLat;
        this.xDelt = (this.maxLon - this.minLon) / this.width;
        this.yDelt = (this.maxLat - this.minLat) / this.height;
        this.g = this.graph.createGraphics();
    }

    /**
     * 保存到本地
     *
     * @param path       路径
     * @param formatName 图片类型（png，jpeg，jpg等）
     * @throws IOException
     */
    public void save(String path, String formatName) {
        try {
            ImageIO.write(graph, formatName, new File(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 销毁绘图对象
     */
    public void dispose() {
        if (g != null) {
            g.dispose();
        }
    }

    /**
     * 填充矩形区域（屏幕坐标）
     *
     * @param rect  矩形范围
     * @param color 填充颜色
     */
    public void fillRectXY(Rectangle2D rect, Color color) {
        g.setColor(color);
        g.fill(rect);
    }

    /**
     * 填充圆形区域（经纬度坐标）
     *
     * @param lon       圆心经度
     * @param lat       圆心纬度
     * @param r         半径（经纬度）
     * @param fillColor 填充颜色
     */
    public void fillCircleLatLon(double lon, double lat, double r, Color fillColor) {
        float[] markLoc = new float[2];
        latLon2XY(markLoc, lon, lat, this.minLon, this.maxLon, this.minLat,
                this.maxLat, this.width, this.height);
        g.setColor(fillColor);
        Ellipse2D ellipse2d = new Ellipse2D.Double(markLoc[0] - r * 0.5f, markLoc[1] - r * 0.5f, r, r);
        g.fill(ellipse2d);
    }


    /**
     * 画点写字
     * @param lon
     * @param lat
     * @param r
     * @param fillColor
     */
    public void drawCircleLatLon(double lon, double lat, double r, Color fillColor, Font font, Color color, String text, TextAlign textAlign) {
        float[] markLoc = new float[2];
        latLon2XY(markLoc, lon, lat, this.minLon, this.maxLon, this.minLat,
                this.maxLat, this.width, this.height);
        g.setColor(fillColor);
        Ellipse2D ellipse2d = new Ellipse2D.Double(markLoc[0] - r * 0.5f, markLoc[1] - r * 0.5f, r, r);
        g.fill(ellipse2d);

        // 面雨量数值
        if (text != null && !text.equals("")) {
            latLon2XY(markLoc, lon, lat + 0.1, this.minLon, this.maxLon, this.minLat,
                    this.maxLat, this.width, this.height);
            drawText(text, font, color, markLoc[0], markLoc[1], textAlign);
        }

    }

    /**
     * 填充方形区域（经纬度坐标）
     *
     * @param lon       中心点经度
     * @param lat       中心点纬度
     * @param r         正方形边长（经纬度）
     * @param fillColor 填充颜色
     */
    public void fillSquare(double lon, double lat, double r, Color fillColor) {
        float[] markLoc = new float[2];
        latLon2XY(markLoc, lon, lat, this.minLon, this.maxLon, this.minLat,
                this.maxLat, this.width, this.height);
        g.setColor(fillColor);
        Rectangle2D rectangle2d = new Rectangle2D.Double(markLoc[0] - r * 0.5f, markLoc[1] - r * 0.5f, r, r);
        g.fill(rectangle2d);
    }

    /**
     * 绘制气泡
     *
     * @param bx           气泡左上角x坐标（屏幕坐标）
     * @param by           气泡左上角y坐标（屏幕坐标）
     * @param bwidth       气泡宽
     * @param bheight      气泡高
     * @param bFillColor   气泡填充颜色
     * @param bBorderColor 边框颜色
     * @param bfont        内置文字字体
     * @param fontColor    文字颜色
     * @param texts        气泡内置文字（一个字符串默认占一样）
     * @param lon          气泡尖角点经度
     * @param lat          气泡尖角点纬度
     */
    public void drawBubble(int bx, int by, int bwidth, int bheight, Color bFillColor, Color bBorderColor,
                           Font bfont, Color fontColor, String[] texts, double lon, double lat) {
        //绘制气泡（圆角矩形）
        RoundRectangle2D rrect = new RoundRectangle2D.Double(bx, by, bwidth, bheight, 0.1 * bwidth, 0.1 * bheight);
        g.setStroke(new BasicStroke(2));
        g.setColor(bBorderColor);
        g.draw(rrect);
        //绘制三角箭头
        float[] markLoc = new float[2];
        latLon2XY(markLoc, lon, lat, this.minLon, this.maxLon, this.minLat,
                this.maxLat, this.width, this.height);

        //气泡中心点坐标为
        double bCenX = bx + 0.5 * bwidth;
        double bCenY = by + 0.5 * bheight;

        PolygonEx polyEx = new PolygonEx();
        polyEx.addPoint((float) bCenX + 20, (float) bCenY);
        polyEx.addPoint((float) bCenX, (float) bCenY);
        polyEx.addPoint(markLoc[0], markLoc[1]);

        g.setStroke(new BasicStroke(3f));
        g.draw(polyEx);
        g.setColor(bFillColor);
        g.fill(polyEx);
        g.fill(rrect);

        g.setStroke(new BasicStroke());

        float startX = bx + 0.05f * bwidth;
        float startY = by;
        for (int i = 0; i < texts.length; i++) {
            //标注气泡文字
            g.setFont(bfont);
            g.setColor(fontColor);
            g.drawString(texts[i], startX, startY + (i + 1) * g.getFontMetrics().getHeight());
        }
    }

    /**
     * 绘制格点数据（格点填色）
     *
     * @param gridData
     * @param gridX
     * @param gridY
     * @param contourValues
     * @param colors
     */
    public void drawGridMap(double[][] gridData, double[] gridX,
                            double[] gridY, double[] contourValues, Color colors[]) {
        PolygonEx pEx = new PolygonEx();
        float dx = 1f * this.width / gridX.length;
        float dy = 1f * this.height / gridY.length;

        for (int i = 0; i < gridY.length; i++) {
            for (int j = 0; j < gridX.length; j++) {
                pEx.reset();
                pEx.addPoint(j * dx, i * dy);
                pEx.addPoint((j + 1) * dx, i * dy);
                pEx.addPoint((j + 1) * dx, (i + 1) * dy);
                pEx.addPoint(j * dx, (i + 1) * dy);
                for (int j2 = 1; j2 < contourValues.length; j2++) {
                    if (gridData[i][j] > contourValues[j2 - 1]
                            && gridData[i][j] < contourValues[j2]) {
                        g.setColor(colors[j2]);
                        g.fill(pEx);
                        break;
                    }
                }
            }
        }
    }

    /**
     * 绘制等值线
     *
     * @param gridData
     * @param gridX
     * @param gridY
     * @param contourValues
     */
    public void drawContourLines(double[][] gridData, double[] gridX,
                                 double[] gridY, double[] contourValues) {
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);

        List<Border> borders;
        List<PolyLine> contourLines;
        List<wContour.Global.Polygon> polygons;
        // 追踪等值线
        int nc = contourValues.length;
        int[][] S1 = new int[gridData.length][gridData[0].length];
        borders = Contour
                .tracingBorders(gridData, gridX, gridY, S1, 9999);
        contourLines = Contour.tracingContourLines(gridData, gridX, gridY, nc,
                contourValues, 9999, borders, S1);
        contourLines = Contour.smoothLines(contourLines);
        polygons = Contour.tracingPolygons(gridData, contourLines,
                borders, contourValues);
        float[] pointf = new float[2];
        PolygonEx pEx = new PolygonEx();
        // 绘制多边形
        if (polygons != null && polygons.size() > 0) {
            Stroke s = new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
            g.setStroke(s);
            g.setColor(Color.BLACK);
            for (int i = 0; i < polygons.size(); i++) {
                pEx.reset();
                List<wContour.Global.PointD> pointdList = polygons.get(i).OutLine.PointList;
                for (wContour.Global.PointD pointD : pointdList) {
                    latLon2XY(pointf, pointD.X, pointD.Y, this.minLon,
                            this.maxLon, this.minLat, this.maxLat, this.width,
                            this.height);
                    pEx.addPoint(pointf[0], pointf[1]);
                }
                g.draw(pEx);
            }
        }
    }

    /**
     * 绘制色斑图
     *
     * @param gridData
     * @param gridX
     * @param gridY
     * @param contourValues
     * @param colors
     */
    public void drawColorMap(double[][] gridData, double[] gridX,
                             double[] gridY, double[] contourValues, Color colors[],double undefData) {
        List<Border> borders;
        List<PolyLine> contourLines;
        List<wContour.Global.Polygon> polygons;
        // 追踪等值线
        int nc = contourValues.length;
        int[][] S1 = new int[gridData.length][gridData[0].length];
        borders = Contour
                .tracingBorders(gridData, gridX, gridY, S1, undefData);
        contourLines = Contour.tracingContourLines(gridData, gridX, gridY, nc,
                contourValues, undefData, borders, S1);
        contourLines = Contour.smoothLines(contourLines);
        polygons = Contour.tracingPolygons(gridData, contourLines,
                borders, contourValues);


        double value;
        int index;
        Color color;
        float[] pointf = new float[2];
        PolygonEx pEx = new PolygonEx();
        // 绘制色斑图
        if (polygons != null && polygons.size() > 0) {
            for (int i = 0; i < polygons.size(); i++) {
                pEx.reset();
                value = polygons.get(i).LowValue;
                index = indexOfArray(contourValues, value);
                color = colors[index + 1];
                if (!polygons.get(i).IsHighCenter) {
                    color = colors[index];
                }
                List<wContour.Global.PointD> pointdList = polygons.get(i).OutLine.PointList;
                for (wContour.Global.PointD pointD : pointdList) {
                    latLon2XY(pointf, pointD.X, pointD.Y, this.minLon,
                            this.maxLon, this.minLat, this.maxLat, this.width,
                            this.height);
                    pEx.addPoint(pointf[0], pointf[1]);
                }
                g.setColor(color);
                g.fill(pEx);
            }
        }
    }

    /**
     * 绘制图片(铺满)
     *
     * @param coverImg
     */
    public void drawCoverImg(BufferedImage coverImg) {
        drawCoverImg(coverImg, 0, 0, coverImg.getWidth(), coverImg.getHeight());
    }

    /**
     * 绘制图片
     *
     * @param coverImg 图片
     * @param x        左上角x
     * @param y        左上角y
     * @param width    绘制宽度
     * @param height   绘制高度
     */
    public void drawCoverImg(BufferedImage coverImg, int x, int y, int width,
                             int height) {
        g.drawImage(coverImg, x, y, width, height, null);
    }


    /**
     * 绘制图片
     * @param coverImg 图片
     * @param lonMin 图片最小经度
     * @param lonMax 图片最大经度
     * @param latMin 图片最小纬度
     * @param latMax 图片最大纬度
     */
    public void drawCoverImg(BufferedImage coverImg, double lonMin, double lonMax,
                             double latMin, double latMax) {
        float[] leftUp = new float[2];
        float[] rightDown = new float[2];
        latLon2XY(leftUp, lonMin, latMax, this.minLon, this.maxLon, this.minLat,
                this.maxLat, this.width, this.height);
        latLon2XY(rightDown, lonMax, latMin, this.minLon, this.maxLon, this.minLat,
                this.maxLat, this.width, this.height);
        g.drawImage(coverImg, (int) leftUp[0], (int) leftUp[1],
                (int) rightDown[0], (int) rightDown[1], 0, 0,
                coverImg.getWidth(), coverImg.getHeight(), null);
    }

    /**
     * 绘制文字标注（屏幕坐标）
     *
     * @param text   文字内容
     * @param font   字体
     * @param color  颜色
     * @param x      x
     * @param y      y
     * @param layout 对齐方式
     */
    public void drawText(String text, Font font, Color color, float x, float y,
                         TextAlign layout) {
        g.setColor(color);
        g.setFont(font);
        if (layout == TextAlign.TEXT_CENTER) {
            g.drawString(text, x - g.getFontMetrics().stringWidth(text) * 0.5f,
                    y);
        } else if (layout == TextAlign.TEXT_LEFT) {
            g.drawString(text, x, y);
        } else if (layout == TextAlign.TEXT_RIGHT) {
            g.drawString(text, x - g.getFontMetrics().stringWidth(text), y);
        }
    }


    public void drawLegend_Level(int x, int y, float cell_w, float cell_h,
                                 String[] levels, Color[] colors, String unit, Font font) {

        // 绘制单位说明
        g.setFont(font);
        g.drawString(unit, x, y + g.getFont().getSize() * 0.5f);

        // 绘制图例
        for (int i = 0; i < colors.length; i++) {
            // 绘制色卡
            g.setColor(colors[i]);
            g.fill(new Rectangle2D.Float(x, y + (1 + i) * cell_h * 1.5f,
                    cell_w, cell_h));
            // 绘制色卡标注
            g.setColor(Color.BLACK);
            g.setFont(font);
            g.drawString(levels[i], x + cell_w * 1.2f, y + (1 + i) * cell_h
                    * 1.5f + cell_h * 0.8f);
        }
    }

    public void drawLegend_Rectangle_V(int x, int y, float cell_w,
                                       float cell_h, double[] values, Color colors[], String unit,
                                       Font font) {
        // 绘制单位说明
        g.setColor(Color.BLACK);
        g.setFont(font);
        g.drawString(unit, x, y + cell_h - g.getFont().getSize() * 0.5f);
        // 绘制色卡
        for (int i = 0; i < colors.length; i++) {
            g.setColor(colors[i]);
            g.fill(new Rectangle2D.Float(x, y + cell_h * (i + 1), cell_w,
                    cell_h));
            g.setColor(Color.black);
            g.draw(new Rectangle2D.Float(x, y + cell_h * (i + 1), cell_w,
                    cell_h));
        }
        // 绘制色卡标注
        g.setColor(Color.BLACK);
        g.setFont(font);
        float dx, dy;
        for (int i = 0; i < values.length; i++) {
            dx = x + 1.5f * cell_w;
            dy = y + cell_h * (i + 2) + g.getFont().getSize() * 0.5f;// +
            // g.getFont().getSize()
            // *
            // 0.5f;
            g.drawString((int) values[i] + "", dx, dy);
        }
    }

    /**
     * 绘制水平摆放的矩形图例
     *
     * @param x      绘制位置X坐标
     * @param y      绘制位置Y坐标
     * @param cell_w 色块宽
     * @param cell_h 色块高
     * @param values 色块分界值
     * @param colors 色块颜色值
     * @param unit   单位标注
     * @param font   字体
     * @param align  对齐方式
     */
    public void drawLegend_Rectangle_H(int x, int y, float cell_w,
                                       float cell_h, double[] values, Color colors[], String unit,
                                       Font font, TextAlign align) {
        if (align == TextAlign.TEXT_RIGHT) {
            x = (int) (x - cell_w * (colors.length + 0.5f) - g.getFontMetrics(
                    font).stringWidth(unit));
        } else if (align == TextAlign.TEXT_CENTER) {
            x = (int) (x - 0.5f * cell_w * (colors.length + 0.5f) - 0.5f * g
                    .getFontMetrics(font).stringWidth(unit));
        }

        // 绘制单位说明
        g.setFont(font);
        g.setColor(Color.BLACK);
        g.drawString(unit, x + cell_w * (colors.length + 0.5f), y + cell_h);
        // 绘制色卡
        for (int i = 0; i < colors.length; i++) {
            g.setColor(colors[i]);
            g.fill(new Rectangle2D.Float(x + cell_w * i, y, cell_w, cell_h));
            g.setColor(Color.black);
            g.draw(new Rectangle2D.Float(x + cell_w * i, y, cell_w, cell_h));
        }
        // 绘制色卡标注
        g.setColor(Color.BLACK);
        g.setFont(font);
        float dx, dy;
        for (int i = 0; i < values.length; i++) {
            dx = x + cell_w * (i + 1) - 0.5f
                    * g.getFontMetrics().stringWidth((int) values[i] + "");
            dy = y + +cell_h * 2;
            g.drawString((int) values[i] + "", dx, dy);
        }

    }

    public void drawLegend_Triangle(int x, int y, float cell_w, float cell_h,
                                    double[] contourValues, Color colors[], String unit, Font font) {
        // 4 绘制图例
        // 4.1绘制色卡
        // 绘制首尾
        g.setColor(colors[0]);
        g.fill(new PolygonEx(new float[]{x, x + cell_w, x + 0.5f * cell_w},
                new float[]{y + 2 * cell_h, y + 2 * cell_h, y + cell_h}, 3));
        g.setColor(Color.BLACK);
        g.draw(new PolygonEx(new float[]{x, x + cell_w, x + 0.5f * cell_w},
                new float[]{y + 2 * cell_h, y + 2 * cell_h, y + cell_h}, 3));

        g.setColor(colors[colors.length - 1]);
        g.draw(new PolygonEx(new float[]{x, x + cell_w, x + 0.5f * cell_w},
                new float[]{y + colors.length * cell_h,
                        y + colors.length * cell_h,
                        y + (colors.length + 1) * cell_h}, 3));
        g.setColor(Color.BLACK);
        g.draw(new PolygonEx(new float[]{x, x + cell_w, x + 0.5f * cell_w},
                new float[]{y + colors.length * cell_h,
                        y + colors.length * cell_h,
                        y + (colors.length + 1) * cell_h}, 3));
        // 绘制其他
        for (int i = 1; i < colors.length - 1; i++) {
            g.setColor(colors[i]);
            g.fill(new Rectangle2D.Float(x, y + cell_h * (i + 1), cell_w,
                    cell_h));
            g.setColor(Color.black);
            g.draw(new Rectangle2D.Float(x, y + cell_h * (i + 1), cell_w,
                    cell_h));
        }
        // 4.2绘制色卡标注
        g.setColor(Color.BLACK);
        g.setFont(font);
        float dx, dy;
        for (int i = 0; i < contourValues.length; i++) {
            dx = x + 1.5f * cell_w;
            dy = y + cell_h * (i + 2) + g.getFont().getSize() * 0.5f;// +
            // g.getFont().getSize()
            // *
            // 0.5f;
            g.drawString((int) contourValues[i] + "", dx, dy);
        }

        // 绘制单位说明
        g.drawString(unit, x, y + cell_h - g.getFont().getSize() * 0.5f);
    }


    public void drawLegend1(int x, int y, float cell_w, float cell_h,
                            double[] contourValues, Color colors[], String unit, Font font) {
        // 4 绘制图例
        // 4.1绘制色卡
        for (int i = 1; i < colors.length; i++) {
            g.setColor(colors[i]);
            g.fill(new Rectangle2D.Float(x, y + cell_h * 1.2f * i, cell_w,
                    cell_h));
        }
        // 4.2绘制色卡标注
        g.setColor(Color.BLACK);
        g.setFont(font);
        float dx, dy;
        for (int i = 1; i < colors.length; i++) {
            dx = x + cell_w * 1.2f;
            dy = y + cell_h * 1.2f * i + cell_h * 0.5f + g.getFont().getSize()
                    * 0.5f;
            if (i == 1) {
                g.drawString(String.format("0-%.0f%s", contourValues[i], unit), dx, dy);
            } else if (i == colors.length - 1) {
                g.drawString(String.format(">=%.0f%s", contourValues[i - 1], unit), dx, dy);
            } else {
                g.drawString(String.format("%.0f-%.0f%s", contourValues[i - 1], contourValues[i], unit), dx, dy);
            }
        }
    }

    public void drawLegend2(int x, int y, float cell_w, float cell_h,
                            double[] contourValues, Color colors[], String unit, Font font) {
        // 4 绘制图例
        // 4.1绘制色卡
        for (int i = 0; i < colors.length; i++) {
            g.setColor(colors[i]);
            g.fill(new Rectangle2D.Float(x, y + cell_h * (i + 1), cell_w,
                    cell_h));
            g.setColor(Color.black);
            g.draw(new Rectangle2D.Float(x, y + cell_h * (i + 1), cell_w,
                    cell_h));
        }
        // 4.2绘制色卡标注
        g.setColor(Color.BLACK);
        g.setFont(font);
        float dx, dy;
        for (int i = 0; i < contourValues.length; i++) {
            dx = x + 1.5f * cell_w;
            dy = y + cell_h * (i + 2) + g.getFont().getSize() * 0.5f;// +
            // g.getFont().getSize()
            // *
            // 0.5f;
            g.drawString((int) contourValues[i] + "", dx, dy);
        }

        // 绘制单位说明
        g.drawString(unit, x, y + cell_h - g.getFont().getSize() * 0.5f);
    }

    public void drawLegend3(int x, int y, float cell_w, float cell_h,
                            List<HashMap<String, Object>> colors, String unit, Font font) {
        // 4 绘制图例
        // 4.1绘制色卡
        for (int i = 1; i < colors.size() - 1; i++) {
            g.setColor((Color) colors.get(i).get("color"));
            g.fill(new Rectangle2D.Float(x + cell_w * i, y, cell_w, cell_h));
        }
        // 4.2绘制色卡标注
        g.setColor(Color.BLACK);
        g.setFont(font);
        float dx, dy;
        for (int i = 1; i < colors.size() - 1; i++) {
            dx = x + cell_w * i;
            dy = y + 1.5f * cell_h + g.getFont().getSize() * 0.5f;
            g.drawString(
                    String.format("%.0f", (Double) colors.get(i).get("max")),
                    dx, dy);
        }

        // 绘制单位说明
        g.drawString(unit, x, y + cell_h - g.getFont().getSize() * 0.5f);
    }

    public void drawRect(Color color, float stroke, int x, int y, int width,
                         int height) {
        g.setColor(color);
        g.setStroke(new BasicStroke(stroke));// 设置边框宽度
        g.drawRect(x, y, width, height);
        g.setStroke(new BasicStroke());
    }

    // 绘制落区
    public void drawColorArea(Color color, PolygonEx polygon) {
        float[] pointf = new float[2];
        // 分区
        g.setColor(color);
        PolygonEx xyPolygon = new PolygonEx();
        for (int i = 0; i < polygon.npoints; i++) {
            latLon2XY(pointf, polygon.xpoints[i], polygon.ypoints[i],
                    this.minLon, this.maxLon, this.minLat, this.maxLat,
                    this.width, this.height);
            xyPolygon.addPoint(pointf[0], pointf[1]);
        }
        g.fill(xyPolygon);
        g.setColor(Color.black);
        g.draw(xyPolygon);
    }

    public void drawContourLine(double locX, double locY, double value,
                                double[] xs, double[] ys, Color color, Font font) {
        float[] pointf = new float[2];
        // 分区
        g.setColor(color);
        PolygonEx xyPolygon = new PolygonEx();
        for (int i = 0; i < xs.length; i++) {
            latLon2XY(pointf, xs[i], ys[i], this.minLon, this.maxLon,
                    this.minLat, this.maxLat, this.width, this.height);
            xyPolygon.addPoint(pointf[0], pointf[1]);
        }
        g.draw(xyPolygon);
        g.setStroke(new BasicStroke(2f));
        drawTextLatLon(font, Color.black, value + "", locX, locY,
                TextAlign.TEXT_CENTER);
    }

    public void drawPolyLine(double[] xs, double[] ys, float storke, Color color) {
        float[] pointf1 = new float[2];
        float[] pointf2 = new float[2];
        Line2D line = new Line2D.Double();
        g.setStroke(new BasicStroke(storke));
        g.setColor(color);
        for (int i = 0; i < xs.length - 1; i++) {
            latLon2XY(pointf1, xs[i], ys[i], this.minLon, this.maxLon,
                    this.minLat, this.maxLat, this.width, this.height);
            latLon2XY(pointf2, xs[i + 1], ys[i + 1], this.minLon, this.maxLon,
                    this.minLat, this.maxLat, this.width, this.height);
            line.setLine(pointf1[0], pointf1[1], pointf2[0], pointf2[1]);
            g.draw(line);
        }


    }

    public void drawTextLatLon(Font font, Color color, String text, double lon,
                               double lat, TextAlign textAlign) {
        float[] pointf = new float[2];
        // 面雨量数值
        if (text != null && !text.equals("")) {
            latLon2XY(pointf, lon, lat, this.minLon, this.maxLon, this.minLat,
                    this.maxLat, this.width, this.height);
            drawText(text, font, color, pointf[0], pointf[1], textAlign);
        }
    }

    private static void latLon2XY(float[] xy, double lon, double lat,
                                  double xMin, double xMax, double yMin, double yMax, int width,
                                  int height) {
        xy[0] = (float) ((lon - xMin) / (xMax - xMin) * width);
        xy[1] = (float) ((yMax - lat) / (yMax - yMin) * height);
    }

    public static Color getOppsiteColor(Color c) {
        return new Color(255 - c.getRed(), 255 - c.getGreen(), 255 - c.getBlue());
    }

    /**
     * 读取pgw文件图片范围
     * @param pgwPath pgw文件路径
     * @param width pgw文件对应图片宽度
     * @param height pgw文件对应图片高度
     * @return  范围数组,依次为 lonmin lonmax latmin latmax
     * @throws Exception
     */
    public static double[] getPgwBound(String pgwPath, int width, int height)
            throws Exception {
        double[] bound = new double[4];
        String[] twfInfo = new String[6];
        FileReader fReader = null;
        BufferedReader brReader = null;
        try {
            fReader = new FileReader(new File(pgwPath));
            brReader = new BufferedReader(fReader);
            for (int i = 0; i < 6; i++) {
                twfInfo[i] = brReader.readLine();
            }
            bound[0] = Double.parseDouble(twfInfo[4]);
            bound[1] = Double.parseDouble(twfInfo[4]) + width
                    * Double.parseDouble(twfInfo[0]);
            bound[2] = Double.parseDouble(twfInfo[5]) + height
                    * Double.parseDouble(twfInfo[3]);
            bound[3] = Double.parseDouble(twfInfo[5]);

            return bound;
        } catch (Exception e) {
            throw e;
        } finally {
            if (brReader != null) {
                brReader.close();
            }
            if (fReader != null) {
                fReader.close();
            }
        }
    }

    private static int indexOfArray(double[] array, double value) {
        int n = -1;
        for (int i = 0; i < array.length; i++) {
            if (array[i] == value) {
                n = i;
                break;
            }
        }
        return n;
    }
}
